package com.windo.animationview;

import java.util.Vector;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class AnimationView extends View {
	Paint _Paint;

	private Bitmap _redBallBitmap;
	private int ball_width;
	int b_width;
	int b_height;
	private Vector<Bubble> ball_vector;
	private Handler _refreshHandler = new Handler();
	private Typeface mFace;
	private String _someText = "Hello";
	private int bubbleID = -1;
	/**
	 * Constructor. This version is only needed if you will be instantiating the
	 * object manually (not from a layout XML file).
	 * 
	 * @param context
	 */
	public AnimationView(Context context) {
		super(context);
		// mFace = Typeface.createFromAsset(getContext().getAssets(), "sans");
		// initLabelView();
	}

	/**
	 * Construct object, initializing with any attributes we understand from a
	 * layout file. These attributes are defined in
	 * SDK/assets/res/any/classes.xml.
	 * 
	 * @see android.view.View#View(android.content.Context,
	 *      android.util.AttributeSet)
	 */
	public AnimationView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// mFace = Typeface.createFromAsset(getContext().getAssets(), "sans");
		mFace = Typeface.create("SANS_SERIF", Typeface.BOLD);

	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		b_width = MeasureSpec.getSize(widthMeasureSpec);
		b_height = MeasureSpec.getSize(heightMeasureSpec);
		initBubbleView();

	}

	private final void initBubbleView() {

		_Paint = new Paint();
		_Paint.setColor(Color.GREEN);
		_redBallBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.red_bubble);
		ball_width = _redBallBitmap.getWidth();
		Bubble.box_width = b_width;
		Bubble.box_height = b_height;
		ball_vector = new Vector<Bubble>();
		add_ball();
		_refreshHandler.postDelayed(UpdateViewTask, 1000);
	}

	// *************** Add a bouncing ball to the Applet ******************
	public void add_ball() {
		add_ball((int) (Math.random() * (Bubble.box_width - ball_width)), (int) (Math.random() * (Bubble.box_height - ball_width)));
	}

	public void add_ball(int x, int y) {

		int initial_x = x;
		int initial_y = y;
		int intial_delta_x = (int) (Math.random() * 2) + 1;
		int intial_delta_y = (int) (Math.random() * 2) + 1;
		ball_vector.addElement(new Bubble(initial_x, initial_y, intial_delta_x, intial_delta_y, ball_width, _redBallBitmap));
	}

	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		for (int i = 0; i < ball_vector.size(); i++) {
			Bubble hold_ball = (Bubble) ball_vector.elementAt(i);

			canvas.drawBitmap(hold_ball.ball_pic, hold_ball.pos_x, hold_ball.pos_y, null);
			_Paint.setTypeface(mFace);

			int w = (int) _Paint.measureText(_someText);
			Rect bounds = new Rect();
			_Paint.getTextBounds(_someText, 0, _someText.length(), bounds);
			canvas.drawText(_someText, hold_ball.pos_x + (hold_ball.ball_width - w) / 2, hold_ball.pos_y + (hold_ball.ball_width / 2 - bounds.height() / 2),
					_Paint);
			Log.v("onDraw", "w=" + w + " bounds.width=" + bounds.width() + " bounds.height()=" + bounds.height());
		}

	}

	private Runnable UpdateViewTask = new Runnable() {
		public void run() {
			collision_detect();
			move_balls();
			invalidate();
			_refreshHandler.postDelayed(this, 25);
		}
	};

	//  Move the balls
	public void move_balls() {
		for (int i = 0; i < ball_vector.size(); i++) {
			((Bubble) ball_vector.elementAt(i)).move_ball();
		}
	}

	// ********************* Collsion detection ********************
	public void collision_detect() {
		int A, B;
		double C;
		int curr_ball;
		int hold_delta_x;
		int hold_delta_y;

		for (curr_ball = 0; curr_ball < ball_vector.size(); curr_ball++) {
			for (int i = 0; i < ball_vector.size(); i++) {
				if (i != curr_ball) {
					Bubble hold_curr_ball = (Bubble) ball_vector.elementAt(curr_ball);
					Bubble hold_check_ball = (Bubble) ball_vector.elementAt(i);
					A = Math.abs(hold_curr_ball.center_x - hold_check_ball.center_x);
					B = Math.abs(hold_curr_ball.center_y - hold_check_ball.center_y);
					C = Math.sqrt((A * A) + (B * B));
					if (C < (hold_curr_ball.radius + hold_check_ball.radius)) {
						hold_delta_x = hold_curr_ball.delta_x;
						hold_delta_y = hold_curr_ball.delta_y;
						hold_curr_ball.set_delta(hold_check_ball.delta_x, hold_check_ball.delta_y);
						hold_check_ball.set_delta(hold_delta_x, hold_delta_y);
						hold_curr_ball.move_ball();
						hold_check_ball.move_ball();
					}
				}
			}
		}
	}



	public boolean onTouchEvent(MotionEvent event) {
		int eventAction = event.getAction();
		int x = (int) event.getX();
		int y = (int) event.getY();

		switch (eventAction) {

		case MotionEvent.ACTION_DOWN: 
			for (int i = 0; i < ball_vector.size(); i++) {
				Bubble curBall = (Bubble) ball_vector.elementAt(i);
				if (curBall.isInside(x, y)) {
					Log.d("onTouchEvent", "inside ball coords!!!!!!!!!!!!!!!!!!!!!!!!:" + curBall.pos_x + " coords: " + curBall.pos_y);
					bubbleID = i;
					ball_vector.elementAt(i).set_movable(false);
					break;
				}
			}
			if (bubbleID < 0)
			{
				int new_x = x - ball_width / 2;
				int new_y = y - ball_width / 2;
				if(new_x<=0)
					new_x=1;
				if(new_x>=Bubble.box_width-ball_width)
					new_x = Bubble.box_width-ball_width -1;
				if(new_y<=0)
					new_y=1;
				if(new_y>=Bubble.box_height-ball_width)
					new_y = Bubble.box_height-ball_width -1;
				add_ball(new_x, new_y);
			}


			break;

		case MotionEvent.ACTION_MOVE: // touch drag with the ball
			Log.d("onTouchEvent", "ACTION_MOVE=");
			if (bubbleID >= 0) {
				ball_vector.elementAt(bubbleID).dragBall(x, y);
			}

			break;

		case MotionEvent.ACTION_UP:
			Log.d("onTouchEvent", "bubbleID=" + bubbleID);
			if (bubbleID >= 0 && bubbleID < ball_vector.size()) {
				ball_vector.elementAt(bubbleID).set_movable(true);
				bubbleID = -1;
			}

			break;
		}
		return true;
	}
}
